home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / text / manipulation / snap164.lha / atie.c next >
Encoding:
C/C++ Source or Header  |  1993-11-30  |  10.1 KB  |  354 lines

  1. /* atie.c -- Ascii To Input Event */
  2.  
  3. /* The contents of this file are copyright 1990, Mikael Karlsson.
  4.  * You may use these routines freely in non-commerical programs,
  5.  * provided that some notice of it's use is given in the program
  6.  * and/or documentation.
  7. */
  8.  
  9. #if __SASC
  10. #include "snap.h"
  11. #endif
  12.  
  13. struct HalfMap {
  14.     UBYTE *KeyMapTypes;
  15.     ULONG *KeyMap;
  16.     UBYTE *Capsable;
  17.     UBYTE *Repeatable;
  18. };
  19.  
  20. struct DeadSpec {
  21.     UBYTE ds_Prev1DownCode;
  22.     UBYTE ds_Prev1DownQual;
  23.     UBYTE ds_Prev2DownCode;
  24.     UBYTE ds_Prev2DownQual;
  25. };
  26.  
  27. #define CONTROLBITS ((1 << 5) | (1 << 6))
  28. #define KEYMAPSIZE  64
  29.  
  30. #define S IEQUALIFIER_LSHIFT
  31. #define A IEQUALIFIER_RALT
  32. #define C IEQUALIFIER_CONTROL
  33.  
  34. /* These tables can be found in RKM Libraries & Devices 1.3 */
  35.  
  36. WORD deadQuals[8][10] = {
  37.     { KC_NOQUAL                     , 1, 0                                },
  38.     {                     KCF_SHIFT , 2, 0, S                             },
  39.     {             KCF_ALT           , 2, 0, A                             },
  40.     {             KCF_ALT+KCF_SHIFT , 4, 0, S, A, S+A                     },
  41.     { KCF_CONTROL                   , 2, 0, C                             },
  42.     { KCF_CONTROL+        KCF_SHIFT , 4, 0, S, C, S+C                     },
  43.     { KCF_CONTROL+KCF_ALT           , 4, 0, A, C, A+C                     },
  44.     { KCF_CONTROL+KCF_ALT+KCF_SHIFT , 8, 0, S, A, S+A, C, C+S, C+A, C+S+A }
  45. };
  46.  
  47. WORD normalQuals[8][6] = {
  48.     { KC_NOQUAL                     , 1,   0, 0, 0, 0 },
  49.     {                     KCF_SHIFT , 2,   0, 0, S, 0 },
  50.     {             KCF_ALT           , 2,   0, 0, A, 0 },
  51.     {             KCF_ALT+KCF_SHIFT , 4, S+A, A, S, 0 },
  52.     { KCF_CONTROL                   , 2,   0, 0, C, 0 },
  53.     { KCF_CONTROL+        KCF_SHIFT , 4, C+S ,C, S, 0 },
  54.     { KCF_CONTROL+KCF_ALT           , 4, C+A, C, A, 0 },
  55.     { KCF_CONTROL+KCF_ALT+KCF_SHIFT , 4, S+A, A, S, 0 }
  56. };
  57.  
  58. #define keytype 0
  59. #define combos 1
  60.  
  61. #undef S
  62. #undef A
  63. #undef C
  64.  
  65. STATIC WORD checkNormalQual(four_bytesp, val, type, qualp)
  66. LONG four_bytesp;
  67. UBYTE val;
  68. UWORD type;
  69. UWORD *qualp;
  70. {
  71.     register UBYTE *p = (UBYTE *)four_bytesp; /* codes held in long word  */
  72.     register WORD position;
  73.     register WORD i = normalQuals[type][combos];
  74.  
  75.     position = 4;
  76.  
  77.     while (i--) {
  78.         --position;
  79.         if (p[position] == val) {
  80.             *qualp = normalQuals[type][position + 2];
  81.             return 1;
  82.         }
  83.     }
  84.     return 0;
  85. }
  86.  
  87. WORD checkNormal(p, val, type, qualp)
  88. UBYTE *p;
  89. UBYTE val;
  90. WORD type;
  91. UWORD *qualp;
  92. {
  93.     /* only one way to match a vanilla control key  */
  94.     if (type == KC_VANILLA && (val & CONTROLBITS) == NULL) { /* control vanilla */
  95.         if (checkNormalQual(p, val | CONTROLBITS, type, qualp)) {
  96.             *qualp |= IEQUALIFIER_CONTROL;
  97.             return (1);
  98.         } else {
  99.             return (0);
  100.         }
  101.     } else { /* not a control */
  102.         return (checkNormalQual(p, val, type, qualp));
  103.     }
  104. }
  105.  
  106.  
  107. STATIC WORD checkDead(keybase, val, type, qualp, indexp)
  108. UBYTE *keybase;                      /* note: byte pointer   */
  109. UBYTE val;
  110. WORD type;
  111. UWORD *qualp;
  112. ULONG *indexp;
  113. {
  114.     WORD i;
  115.     WORD j;
  116.     register UBYTE *p = keybase;  /* need to remember keybase for offsets */
  117.     UBYTE *deadp;
  118.  
  119.     /* walk through two-byte entries, one for each qual. combo.       */
  120.     for (i = 0; i < deadQuals[type][combos]; ++i, p += 2) {
  121.         switch (p[0]) {
  122.             case DPF_DEAD:       /* dead keys do not themselves map to anything */
  123.                 break;
  124.             case DPF_MOD:        /* dead key modifiable  */
  125.                 deadp = keybase + p[1];
  126.                 /* look down the string indexed by dead-key     index */
  127.                 for (j = 0; j < 6; ++j) {
  128.                     if (deadp[j] == val) {
  129.                         *qualp = deadQuals[type][i + 2];
  130.                         *indexp = j;
  131.                         return 1;
  132.                     }
  133.                 }
  134.                 break;
  135.             case 0:                      /* normal stroke for this key   */
  136.                 if (p[1] == val) {
  137.                     *qualp = deadQuals[type][i + 2];
  138.                     return 1;
  139.             }
  140.         }
  141.     }
  142.     return (0);
  143. }
  144.  
  145. /*
  146.  * Calculates Code+Qual of previous dead key (should be keys)
  147.  * and puts them in DeapSpec.
  148.  * returns success (1) or failure (0).
  149.  */
  150. STATIC WORD BuildDeadSpec(inx, hm, hms, ds)
  151. ULONG inx;
  152. struct HalfMap *hm;
  153. WORD hms;
  154. struct DeadSpec *ds;
  155. {
  156.     /* find keystroke which generates index */
  157.  
  158.     register WORD code = 0;
  159.     register UBYTE *deadthing;
  160.     register WORD i;
  161.  
  162.     do {
  163.         /* check each deadkey in the table      */
  164.  
  165.         if (hm->KeyMapTypes[code] & KCF_DEAD) {
  166.             register WORD type = hm->KeyMapTypes[code] & 7;
  167.  
  168.             /* keymap entry is pointer to prefix:byte pairs   */
  169.  
  170.             deadthing = (UBYTE *)hm->KeyMap[code];
  171.             for (i = 0; i < deadQuals[type][combos]; ++i, deadthing += 2) {
  172.                   /* check for index prefix and correct index     */
  173.                 if (deadthing[0] == DPF_DEAD &&
  174.                   (deadthing[1] & DP_2DINDEXMASK) == inx) {
  175.                     ds->ds_Prev1DownCode = code;
  176.                     ds->ds_Prev1DownQual = deadQuals[type][i + 2];
  177.                     ds->ds_Prev2DownCode = 0;
  178.                     ds->ds_Prev2DownQual = 0;
  179.                     return 1;
  180.                 }
  181.             }
  182.         }
  183.     } while (++code < hms);
  184.  
  185.     return 0;   /* Not found */
  186. }
  187.  
  188. STATIC WORD checkString(keybase, val, type, qualp)
  189. UBYTE *keybase;                      /* note: byte pointer   */
  190. UBYTE val;
  191. WORD type;
  192. UWORD *qualp;
  193. {
  194.     WORD i;
  195.     register UBYTE *p = keybase;  /* need to remember keybase for offsets */
  196.  
  197.     /* walk through two-byte entries, one for each qual. combo.       */
  198.     for (i = 0; i < deadQuals[type][combos]; ++i, p += 2) {
  199.         if (p[0] == 1) {         /* One char in string */
  200.             if (keybase[p[1]] == val) {   /* Our char? */
  201.                 *qualp = deadQuals[type][i + 2];
  202.                 return 1;
  203.             }
  204.         }
  205.     }
  206.     return (0);
  207. }
  208.  
  209. /* BuildEvent tries to generate an input event.
  210.  * returns success (1) or failure (0).
  211.  */
  212. STATIC UWORD BuildEvent(value, hm, hms, ie, km)
  213. register UBYTE  value;
  214. struct HalfMap *hm;
  215. WORD hms;
  216. struct InputEvent *ie;
  217. struct KeyMap *km;      /* We need this to find dead prefix */
  218. {
  219.     register UWORD code = 0;
  220.     register WORD type;
  221.     register LONG *p;             /* points to four-byte lokeymap entry   */
  222.     UWORD *qualp = &ie->ie_Qualifier;
  223.     WORD found_it = 0;
  224.     ULONG index = 0;
  225.  
  226.     p = (LONG *) hm->KeyMap;
  227.  
  228.     do  {
  229.         type = hm->KeyMapTypes[code];
  230.         /* determine type of key        */
  231.         if (type & KCF_STRING) {
  232.             found_it = checkString((UBYTE *)*p, value, type & 7, qualp);
  233.         } else if (type & KCF_DEAD) {
  234.             found_it = checkDead((UBYTE *)*p, value, type & 7, qualp, &index);
  235.         } else if (!(type & KCF_NOP)) {
  236.             found_it = checkNormal((LONG)p, value, type & 7, qualp);
  237.         }
  238.         ++p;
  239.     } while (!found_it && ++code < hms);
  240.  
  241.     if (found_it) {
  242.         ie->ie_Code = code;
  243.           /* Successful BuildEvent. Check for dead key. */
  244.         if (index) {
  245.             struct HalfMap *dhm;
  246.             struct DeadSpec *ds = (struct DeadSpec *)&ie->ie_EventAddress;
  247.  
  248.             dhm = (struct HalfMap *)&km->km_LoKeyMapTypes;
  249.             if (BuildDeadSpec(index, dhm, 64, ds)) {
  250.                 return 1;
  251.             }
  252.             dhm = (struct HalfMap *)&km->km_HiKeyMapTypes;
  253.             if (BuildDeadSpec(index, dhm, 56, ds)) {
  254.                 return 1;
  255.             }
  256.             return 0;   /* Couldn't find index generating dead key */
  257.         } else {
  258.             return 1;
  259.         }
  260.     } else {
  261.         return 0;
  262.     }
  263. }
  264.  
  265. /*
  266.  * NAME
  267.  *      AsciiToInputEvent -- build input event to generate ascii
  268.  *
  269.  * SYNOPSIS
  270.  *      success = AsciiToInputEvent(ascii, inputevent, keymap)
  271.  *      ULONG AsciiToInputEvent(ULONG, struct InputEvent *, struct KeyMap *)
  272.  *
  273.  * FUNCTION
  274.  *      This function tries to generate an input event that, when sent
  275.  *      to the input handler, will generate the specified ascii code.
  276.  *
  277.  * INPUTS
  278.  *      ascii - the ascii code to be generated by the constructed
  279.  *              input event.
  280.  *
  281.  *      inputevent - the input event that will be filled will the
  282.  *              appropriate values to generate the given ascii code.
  283.  *
  284.  *      keymap - the keymap that the input event will be reverse-
  285.  *              engineered from.
  286.  *
  287.  *
  288.  * RESULT
  289.  *      success - a boolean value indicating whether the reverse-
  290.  *              engineering was successful.
  291.  *
  292.  * NOTE
  293.  *      The ascii code must be available in the given keymap to be
  294.  *      generatable. Ascii values between 128 and 160 are usually
  295.  *      not available with normal keymaps.
  296.  *
  297.  * SEE ALSO
  298.  *      RawKeyConvert(), V36 keymap.library/MapANSI().
  299.  */
  300.  
  301. ULONG AsciiToInputEvent(ascii, ie, km)
  302. ULONG ascii;
  303. register struct InputEvent *ie;
  304. struct KeyMap *km;
  305. {
  306.     struct HalfMap *hm;
  307.  
  308.     ie->ie_Class = IECLASS_RAWKEY;
  309.     ie->ie_Qualifier = 0;
  310.     ie->ie_EventAddress = 0;
  311.  
  312.     /* Some ascii values has to be treated separately
  313.        since some programs know the difference between
  314.        for example CTRL-M and RETURN.  */
  315.     {
  316.         WORD code = 0;
  317.  
  318.         switch(ascii)
  319.         {
  320.             case 0x08:              /* backspace  */
  321.                 code = 0x41;
  322.                 break;
  323.             case '\t':              /* tab        */
  324.                 code = 0x42;
  325.                 break;
  326.             case 0x0D:              /* return     */
  327.                 code = 0x44;
  328.                 break;
  329.             case 0x1B:              /* esc        */
  330.                 code = 0x45;
  331.                 break;
  332.             case 0x7F:              /* del        */
  333.                 code = 0x46;
  334.                 break;
  335.         }
  336.  
  337.         if (code) {
  338.             ie->ie_Code = code;
  339.             return 1;
  340.         }
  341.     }
  342.  
  343.     hm = (struct HalfMap *)&km->km_LoKeyMapTypes;
  344.     if (BuildEvent((UBYTE)ascii, hm, 64, ie, km)) {
  345.         return 1;   /* Key found in LoKeyMap */
  346.     }
  347.     hm = (struct HalfMap *)&km->km_HiKeyMapTypes;
  348.     if (BuildEvent((UBYTE)ascii, hm, 56, ie, km)) {
  349.         ie->ie_Code += 64;  /* Don't forget that we're in the hi keymap */
  350.         return 1;   /* Key found in HiKeyMap */
  351.     }
  352.     return 0;     /* No luck */
  353. }
  354.